// #define _GNU_SOURCE
#pragma once
#include <fcntl.h>
#include <stdio.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/timerfd.h>
#include <unistd.h>

//
// #include <stdlib.h>
// #include <string.h>
// #include <iostream>
#include <errno.h>
#include <sys/epoll.h>
#include <sys/syscall.h>

#include <chrono>
#include <iostream>
#include <thread>
#include <unordered_map>
#include <vector>

//
//  https://zhuanlan.zhihu.com/p/409434419  timerfd_create

//  ll /proc/6997/fd/
//  cat /proc/6997/fdinfo/3
//  https://blog.csdn.net/m0_56145255/article/details/124792742  memfd_create

void testTimer() {

  struct itimerspec ts;
  // 第一次超时时间
  ts.it_value.tv_sec = 1; // 初始超时为 1 秒
  ts.it_value.tv_nsec = 0;
  ts.it_interval.tv_sec = 5; // 不设置间隔，定时器只触发一次
  ts.it_interval.tv_nsec = 0;

  // 创建一个 时间 fd
  // int timerfd = ::timerfd_create(CLOCK_MONOTONIC,
  //                                 TFD_NONBLOCK | TFD_CLOEXEC);
  // if (timerfd < 0)
  // {
  //     LOG_SYSFATAL << "Failed in timerfd_create";
  // }

  // 创建 timerfd
  int timerfd = timerfd_create(CLOCK_REALTIME, 0);
  // 设置第一次超时时间和超时间隔
  if (timerfd_settime(timerfd, TFD_TIMER_ABSTIME, &ts, NULL) == -1) {
    return;
  }
  // // 定时器循环
  // for (auto tot_exp = 0; tot_exp < 10;) {
  //     // read timerfd，获取到超时次数
  //     s = read(fd, &exp, sizeof(uint64_t));
  //     // 累计总超时次数
  //     tot_exp += exp;
  //     // 打印超时次数的信息
  //     printf("read: %llu; total=%llu\n", (unsigned long long) exp, (unsigned
  //     long long) tot_exp);
  // }

  fd_set readfds;
  FD_ZERO(&readfds);
  FD_SET(timerfd, &readfds);

  struct timeval tv;
  tv.tv_sec = 1.5; // 等待超时时间为 2 秒
  tv.tv_usec = 0;
  int i = 10;
  while (--i) {
    int ret = select(timerfd + 1, &readfds, NULL, NULL, &tv);
    if (ret == -1) {
      // 处理错误
      std::cout << "timer err==" << std::endl;
    } else if (ret == 0) {
      // 等待超时
      std::cout << "timer overtime ==" << std::endl;
    } else if (FD_ISSET(timerfd, &readfds)) {
      // 定时器到期，处理事件
      std::cout << "timer coms" << std::endl;
    }
  }

  //处理定时器事件
  uint64_t expires;
  ssize_t s = read(timerfd, &expires, sizeof(expires));
  if (s != sizeof(expires)) {
    // 处理错误或异常情况
  }
  // 使用 expires 变量中的值来处理定时器事件

  close(timerfd);
}

// 回调函数类型定义
typedef void (*timer_callback_t)(void);

// 回调函数示例
void timer_callback(uint64_t id) {
  printf("Timer %lu expired!\n", id);
  // 在这里执行你的定时任务
}

void testEpollTimer() {
  int timerfd, epollfd, nfds;
  struct epoll_event ev, events[1];
  struct itimerspec ts;

  // 创建 timerfd
  timerfd = timerfd_create(CLOCK_REALTIME, 0);
  if (timerfd == -1) {
    perror("timerfd_create");
    exit(EXIT_FAILURE);
  }

  // 设置定时器参数
  ts.it_value.tv_sec = 2; // 初始超时为 1 秒
  ts.it_value.tv_nsec = 0;
  ts.it_interval.tv_sec = 2; // 每隔 1 秒再次触发
  ts.it_interval.tv_nsec = 0;

  if (timerfd_settime(timerfd, 0, &ts, NULL) == -1) {
    perror("timerfd_settime");
    exit(EXIT_FAILURE);
  }

  // 创建 epoll 实例
  epollfd = epoll_create1(0);
  if (epollfd == -1) {
    perror("epoll_create1");
    exit(EXIT_FAILURE);
  }

  // 注册 timerfd 到 epoll
  ev.events = EPOLLIN; // 监听可读事件
  ev.data.fd = timerfd;
  if (epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &ev) == -1) {
    perror("epoll_ctl: add");
    exit(EXIT_FAILURE);
  }

  // 事件循环
  for (;;) {
    nfds = epoll_wait(epollfd, events, 1, -1); // 等待事件，不设置超时
    if (nfds == -1) {
      if (errno != EINTR) {
        perror("epoll_wait");
        exit(EXIT_FAILURE);
      }
      continue;
    }

    // 检查是哪个文件描述符的事件
    for (int i = 0; i < nfds; ++i) {
      if (events[i].data.fd == timerfd) {
        // 读取 timerfd 以消耗通知（可以读取到期次数，但在此示例中我们不需要）
        uint64_t exp;
        read(timerfd, &exp, sizeof(exp));

        // 调用回调函数
        timer_callback(exp);
      }
    }
  }

  // 清理并退出
  close(timerfd);
  close(epollfd);
}

void testMemfd() {
  int fd = syscall(SYS_memfd_create, "my_memfd", 0);
  if (fd == -1) {
    perror("memfd_create");
    exit(EXIT_FAILURE);
  }

  const char *data = "Hello, memfd_create!";
  ssize_t bytes_written = write(fd, data, strlen(data));
  if (bytes_written == -1) {
    perror("write");
    close(fd);
    exit(EXIT_FAILURE);
  }

  // 注意：由于 memfd_create 创建一个内存文件，我们通常不会读取它，
  // 但如果你需要，你可以像读取普通文件一样读取它。

  close(fd); // 关闭文件描述符
}

class TimerTask {
public:
  virtual ~TimerTask() {}
  virtual void run() = 0;

private:
  int number;
};

class TimerWheel {
private:
  std::vector<std::vector<TimerTask *>> wheel;
  std::unordered_map<TimerTask *, int> taskIndices;
  int tickInterval; // 每个槽位代表的时间间隔（毫秒）
  int wheelSize;    // 时间轮的大小
  int currentPos;   // 当前位置
  bool running;     // 时间轮是否正在运行

  void tick() {
    // 假设当前槽位到期，执行其中的任务
    auto &expiredTasks = wheel[currentPos];
    for (auto task : expiredTasks) {
      task->run();
      // 可以选择删除任务或重新添加任务
      // 这里我们简单地清空槽位，不再重新添加任务
    }
    expiredTasks.clear();

    // 移动到下一个槽位
    currentPos = (currentPos + 1) % wheelSize;

    // 调度下一次tick
    // 这里使用简单的sleep来模拟，实际中可以使用定时器或线程池
    std::this_thread::sleep_for(std::chrono::milliseconds(tickInterval));
  }

public:
  TimerWheel(int tickIntervalMillis, int wheelSize)
      : tickInterval(tickIntervalMillis), wheelSize(wheelSize), currentPos(0),
        running(false) {
    wheel.resize(wheelSize);
  }

  // 添加任务到时间轮
  void addTask(TimerTask *task, int delayMillis) {
    int targetPos = (currentPos + delayMillis / tickInterval) % wheelSize;
    wheel[targetPos].push_back(task);
    taskIndices[task] = targetPos;
  }

  // 移除任务
  void removeTask(TimerTask *task) {
    auto it = taskIndices.find(task);
    if (it != taskIndices.end()) {
      int targetPos = it->second;
      auto &tasks = wheel[targetPos];
      tasks.erase(std::find_if(tasks.begin(), tasks.end(), task));
      taskIndices.erase(it);
    }
  }

  // 启动时间轮
  void start() {
    running = true;
    while (running) {
      tick();
    }
  }

  // 停止时间轮
  void stop() { running = false; }
};

// 示例的TimerTask实现
class MyTimerTask : public TimerTask {
public:
  void run() override {
    std::cout << "Task executed at "
              << std::chrono::system_clock::now().time_since_epoch().count()
              << "ms\n";
  }

  // 实现相等性比较
  bool operator==(const MyTimerTask &other) const {
    return name == other.name && age == other.age;
  }
};

int testTimeWheel() {
  TimerWheel wheel(1000, 5); // 每秒一个槽位，共5个槽位
  MyTimerTask task;
  wheel.addTask(&task, 3000); // 3秒后执行任务

  wheel.start(); // 启动时间轮

  // 模拟主线程运行一段时间，然后停止时间轮
  std::this_thread::sleep_for(std::chrono::seconds(5));
  wheel.stop();

  return 0;
}